Micron Document
<!DOCTYPE html>
<html class="client-nojs vector-feature-night-mode-disabled vector-feature-language-in-header-enabled vector-feature-language-in-main-page-header-disabled vector-feature-page-tools-pinned-disabled vector-feature-toc-pinned-clientpref-1 vector-feature-main-menu-pinned-disabled vector-feature-limited-width-clientpref-1 vector-feature-limited-width-content-enabled vector-feature-custom-font-size-clientpref-1 vector-feature-appearance-pinned-clientpref-1 vector-sticky-header-enabled" lang="en" dir="ltr"><head>
<meta charset="UTF-8">
<title>Leftist tree</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="canonical" href="https://en.wikipedia.org/wiki/Leftist_tree"> <link href="./mw/ext.cite.styles.css" rel="stylesheet" type="text/css">
<link href="./mw/ext.math.styles.css" rel="stylesheet" type="text/css">
<link href="./mw/ext.pygments.css" rel="stylesheet" type="text/css">
<link href="./mw/mediawiki.page.gallery.styles.css" rel="stylesheet" type="text/css">
<link href="./mw/skins.vector.icons.css" rel="stylesheet" type="text/css">
<link href="./mw/skins.vector.search.codex.styles.css" rel="stylesheet" type="text/css">
<link href="./mw/skins.vector.styles.css" rel="stylesheet" type="text/css">
<link href="./mw/user.styles.css" rel="stylesheet" type="text/css">
<meta name="ResourceLoaderDynamicStyles" content="">
<link rel="stylesheet" type="text/css" href="./mw/site.styles.css">
<link rel="stylesheet" type="text/css" href="./mw/noscript.css">
<link rel="stylesheet" type="text/css" href="./footer.css">
<link rel="stylesheet" type="text/css" href="./vector-2022.css">
</head>
<body class="skin--responsive skin-vector skin-vector-search-vue mediawiki ltr sitedir-ltr mw-hide-empty-elt ns-0 ns-subject page-Leftist_tree rootpage-Leftist_tree skin-vector-2022 action-view">
<div class="mw-page-container">
<div class="mw-page-container-inner">
<div class="mw-content-container">
<main id="content" class="mw-body">
<header class="mw-body-header vector-page-titlebar">
<h1 id="firstHeading" class="firstHeading mw-first-heading">
<span id="openzim-page-title" class="mw-page-title-main"><span class="mw-page-title-main">Leftist tree</span></span>
</h1>
</header>
<a id="top"></a>
<div id="bodyContent" class="vector-body ve-init-mw-desktopArticleTarget-targetContainer" aria-labelledby="firstHeading" data-mw-ve-target-container="">
<div id="mw-content-text" class="mw-body-content mw-content-ltr" lang="en" dir="ltr"><div class="mw-content-ltr mw-parser-output" lang="en" dir="ltr">
<p>In <a href="Computer_science" title="Computer science">computer science</a>, a <b>leftist tree</b> or <b>leftist heap</b> is a <a href="Priority_queue" title="Priority queue">priority queue</a> implemented with a variant of a <a href="Binary_heap" title="Binary heap">binary heap</a>. Every node x has an <i>s-value</i> which is the distance to the nearest <a href="Leaf_node" class="mw-redirect" title="Leaf node">leaf</a> in subtree rooted at x.<sup id="cite_ref-:0_1-0" class="reference"><a href="#cite_note-:0-1"><span class="cite-bracket">[</span>1<span class="cite-bracket">]</span></a></sup> In contrast to a <i>binary heap</i>, a leftist tree attempts to be very unbalanced. In addition to the <a href="Heap_(data_structure)" title="Heap (data structure)">heap</a> property, leftist trees are maintained so the right descendant of each node has the lower s-value.
</p><p>The height-biased leftist tree was invented by Clark Allan Crane.<sup id="cite_ref-Crane1972_2-0" class="reference"><a href="#cite_note-Crane1972-2"><span class="cite-bracket">[</span>2<span class="cite-bracket">]</span></a></sup> The name comes from the fact that the left subtree is usually taller than the right subtree.
</p><p>A leftist tree is a <a href="Mergeable_heap" title="Mergeable heap">mergeable heap</a>. When inserting a new node into a tree, a new one-node tree is created and merged into the existing tree. To delete an item, it is replaced by the merge of its left and right sub-trees. Both these operations take O(log <i>n</i>) time. For insertions, this is slower than <a href="Fibonacci_heap" title="Fibonacci heap">Fibonacci heaps</a>, which support insertion in O(1) (constant) <a href="Amortized" class="mw-redirect" title="Amortized">amortized</a> time, and O(log <i>n</i>) worst-case.
</p><p>Leftist trees are advantageous because of their ability to merge quickly, compared to binary heaps which take Θ(<i>n</i>). In almost all cases, the merging of <a href="Skew_heap" title="Skew heap">skew heaps</a> has better performance. However merging leftist heaps has worst-case O(log <i>n</i>) complexity while merging skew heaps has only amortized O(log <i>n</i>) complexity.
</p>
<meta property="mw:PageProp/toc">
<div class="mw-heading mw-heading2"><h2 id="Bias">Bias</h2></div>
<p>The usual leftist tree is a <i>height-biased</i> leftist tree.<sup id="cite_ref-Crane1972_2-1" class="reference"><a href="#cite_note-Crane1972-2"><span class="cite-bracket">[</span>2<span class="cite-bracket">]</span></a></sup> However, other biases can exist, such as in the <i>weight-biased</i> leftist tree.<sup id="cite_ref-Cho96_3-0" class="reference"><a href="#cite_note-Cho96-3"><span class="cite-bracket">[</span>3<span class="cite-bracket">]</span></a></sup>
</p><p>The exact worst-case complexity of both types of leftist trees is 2 log<sub>2</sub> <i>n</i>, counting comparisons. The exact amortized complexity of weight-biased leftist trees is known to match the log<sub>φ</sub> <i>n</i> (approximately 1.44 log<sub>2</sub> <i>n</i>) exact amortized complexity of skew heaps, where φ denotes the <a href="Golden_ratio" title="Golden ratio">golden ratio</a>; similarly, the amortized complexity of height-biased leftist trees is bounded below by log<sub>φ</sub> <i>n</i>, but whether this is also the upper bound is an open problem.<sup id="cite_ref-Sch24_4-0" class="reference"><a href="#cite_note-Sch24-4"><span class="cite-bracket">[</span>4<span class="cite-bracket">]</span></a></sup>
</p>
<div class="mw-heading mw-heading2"><h2 id="S-value">S-value</h2></div>

<p>The <b>s-value</b> (or <b>rank</b>) of a node is the distance from that node to the nearest empty position in the subtree rooted at that node. Put another way, the s-value of a <code>null</code> child is implicitly zero. Other nodes have an s-value equal to one more the minimum of their children's s-values. Thus, in the example at right, all nodes with at least one missing child have an s-value of 1, while node 4 has an s-value of 2, since its right child (8) has an s-value of 1. (In some descriptions, the s-value of null children is assumed to be −1.<sup id="cite_ref-5" class="reference"><a href="#cite_note-5"><span class="cite-bracket">[</span>5<span class="cite-bracket">]</span></a></sup>)
</p><p>Knowing the shortest path to the nearest missing leaf in the subtree rooted at <i>x</i> is exactly of <i>s</i>(<i>x</i>), every node at depth <i>s</i>(<i>x</i>)−1 or less has exactly 2 children since <i>s</i>(<i>x</i>) would have been less if not. Meaning that the size of the tree rooted at <i>x</i> is at least <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle 2^{s(x)}-1}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<msup>
<mn>2</mn>
<mrow class="MJX-TeXAtom-ORD">
<mi>s</mi>
<mo stretchy="false">(</mo>
<mi>x</mi>
<mo stretchy="false">)</mo>
</mrow>
</msup>
<mo>−<!-- − --></mo>
<mn>1</mn>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle 2^{s(x)}-1}</annotation>
</semantics>
</math></span><img src="./1c8b9044268fd9d38024524af84841e9febf89ed.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.505ex; width:8.388ex; height:3.009ex;" alt="{\displaystyle 2^{s(x)}-1}" loading="lazy"></span>. Thus, <i>s</i>(<i>x</i>) is at most <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle \log {(m+1)}}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>log</mi>
<mo>⁡<!-- ⁡ --></mo>
<mrow class="MJX-TeXAtom-ORD">
<mo stretchy="false">(</mo>
<mi>m</mi>
<mo>+</mo>
<mn>1</mn>
<mo stretchy="false">)</mo>
</mrow>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle \log {(m+1)}}</annotation>
</semantics>
</math></span><img src="./efe13c4efa2d3a001eb944afd318c04ff38de0c4.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.838ex; width:11.211ex; height:2.843ex;" alt="{\displaystyle \log {(m+1)}}" loading="lazy"></span>, <i>m</i> being the number of nodes of the subtree rooted at <i>x</i>.<sup id="cite_ref-:0_1-1" class="reference"><a href="#cite_note-:0-1"><span class="cite-bracket">[</span>1<span class="cite-bracket">]</span></a></sup>
</p>
<div class="mw-heading mw-heading2"><h2 id="Operations_on_a_height_biased_leftist_tree">Operations on a height biased leftist tree</h2></div>
<p>Most operations on a Height Biased Leftist Tree are done using the merge operation.<sup id="cite_ref-:0_1-2" class="reference"><a href="#cite_note-:0-1"><span class="cite-bracket">[</span>1<span class="cite-bracket">]</span></a></sup>
</p>
<div class="mw-heading mw-heading3"><h3 id="Merging_two_Min_HBLTs">Merging two Min HBLTs</h3></div>
<p>The merge operation takes two Min HBLTs as input and returns a Min HBLT containing all the nodes in the original Min HBLTs put together.
</p><p>If either of A or B is empty, the merge returns the other one.
</p><p>In case of Min HBLTs, assume we have two trees rooted at A and B where A.key <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle \leq }">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mo>≤<!-- ≤ --></mo>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle \leq }</annotation>
</semantics>
</math></span><img src="./440568a09c3bfdf0e1278bfa79eb137c04e94035.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.505ex; width:1.808ex; height:2.176ex;" alt="{\displaystyle \leq }" loading="lazy"></span> B.key. Otherwise we can swap A and B so that the condition above holds.
</p><p>The merge is done recursively by merging B with A's right subtree. This might change the S-value of A's right subtree. To maintain the leftist tree property, after each merge is done, we check if the S-value of right subtree became bigger than the S-value of left subtree during the recursive merge calls. If so, we swap the right and left subtrees (If one child is missing, it should be the right one).
</p><p>Since we assumed that A's root is greater than B's, the heap property is also maintained.
</p>
<div class="mw-heading mw-heading4"><h4 id="Pseudocode_for_merging_two_min_height_biased_leftist_trees">Pseudocode for merging two min height biased leftist trees</h4></div>
<pre>MERGE(A, B)
<b>if</b> A = null <b>return</b> B
<b>if</b> B = null <b>return</b> A
<b>if</b> A.key &gt; B.key <b>return</b> MERGE(B, A)
A.right&nbsp;:= MERGE (A.right, B) <i>// the result cannot be null since B is non-null</i>
<b>if</b> A.left = null <b>then</b>
SWAP(A.left, A.right)
A.s_value&nbsp;:= 1 <i>// since the right subtree is null, the shortest path to a descendant leaf from node A is 1</i>
<b>return</b> A
<b>if</b> A.right.s_value &gt; A.left.s_value <b>then</b>
SWAP (A.right, A.left)
A.s_value&nbsp;:= A.right.s_value + 1
<b>return</b> A
</pre>
<div class="mw-heading mw-heading4"><h4 id="Java_code_for_merging_two_min_height_biased_leftist_trees">Java code for merging two min height biased leftist trees</h4></div>
<div class="mw-highlight mw-highlight-lang-java mw-content-ltr" dir="ltr"><pre><span class="kd">public</span><span class="w"> </span><span class="n">Node</span><span class="w"> </span><span class="nf">merge</span><span class="p">(</span><span class="n">Node</span><span class="w"> </span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">Node</span><span class="w"> </span><span class="n">y</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kc">null</span><span class="p">)</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">y</span><span class="p">;</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">y</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kc">null</span><span class="p">)</span><span class="w"> </span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">x</span><span class="p">;</span>

<span class="w"> </span><span class="c1">// if this were a max-heap, then the </span>
<span class="w"> </span><span class="c1">// next line would be: if (x.element &lt; y.element)</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="p">.</span><span class="na">element</span><span class="p">.</span><span class="na">compareTo</span><span class="p">(</span><span class="n">y</span><span class="p">.</span><span class="na">element</span><span class="p">)</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span>
<span class="w"> </span><span class="c1">// x.element &gt; y.element</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">merge</span><span class="w"> </span><span class="p">(</span><span class="n">y</span><span class="p">,</span><span class="w"> </span><span class="n">x</span><span class="p">);</span>

<span class="w"> </span><span class="n">x</span><span class="p">.</span><span class="na">rightChild</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">merge</span><span class="p">(</span><span class="n">x</span><span class="p">.</span><span class="na">rightChild</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="p">);</span>

<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="p">.</span><span class="na">leftChild</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kc">null</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// left child doesn't exist, so move right child to the left side</span>
<span class="w"> </span><span class="n">x</span><span class="p">.</span><span class="na">leftChild</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">x</span><span class="p">.</span><span class="na">rightChild</span><span class="p">;</span>
<span class="w"> </span><span class="n">x</span><span class="p">.</span><span class="na">rightChild</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">null</span><span class="p">;</span>
<span class="w"> </span><span class="c1">// x.s was, and remains, 1</span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// left child does exist, so compare s-values</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="p">.</span><span class="na">leftChild</span><span class="p">.</span><span class="na">s</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">x</span><span class="p">.</span><span class="na">rightChild</span><span class="p">.</span><span class="na">s</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">Node</span><span class="w"> </span><span class="n">temp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">x</span><span class="p">.</span><span class="na">leftChild</span><span class="p">;</span>
<span class="w"> </span><span class="n">x</span><span class="p">.</span><span class="na">leftChild</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">x</span><span class="p">.</span><span class="na">rightChild</span><span class="p">;</span>
<span class="w"> </span><span class="n">x</span><span class="p">.</span><span class="na">rightChild</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">temp</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="c1">// since we know the right child has the lower s-value, we can just</span>
<span class="w"> </span><span class="c1">// add one to its s-value</span>
<span class="w"> </span><span class="n">x</span><span class="p">.</span><span class="na">s</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">x</span><span class="p">.</span><span class="na">rightChild</span><span class="p">.</span><span class="na">s</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">x</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<div class="mw-heading mw-heading4"><h4 id="Haskell_code_for_merging_two_min_height_biased_leftist_trees">Haskell code for merging two min height biased leftist trees</h4></div>
<div class="mw-highlight mw-highlight-lang-haskell mw-content-ltr" dir="ltr"><pre><span class="kr">data</span><span class="w"> </span><span class="kt">LHeap</span><span class="w"> </span><span class="n">a</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Leaf</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">Node</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="p">(</span><span class="kt">LHeap</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="kt">LHeap</span><span class="w"> </span><span class="n">a</span><span class="p">)</span>

<span class="nf">rank</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">LHeap</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="kt">Integer</span>
<span class="nf">rank</span><span class="w"> </span><span class="kt">Leaf</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">0</span>
<span class="nf">rank</span><span class="w"> </span><span class="p">(</span><span class="kt">Node</span><span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="n">r</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">rank</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span>

<span class="nf">merge</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Ord</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=&gt;</span><span class="w"> </span><span class="kt">LHeap</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="kt">LHeap</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="kt">LHeap</span><span class="w"> </span><span class="n">a</span>
<span class="nf">merge</span><span class="w"> </span><span class="kt">Leaf</span><span class="w"> </span><span class="n">h</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">h</span>
<span class="nf">merge</span><span class="w"> </span><span class="n">h</span><span class="w"> </span><span class="kt">Leaf</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">h</span>
<span class="nf">merge</span><span class="w"> </span><span class="n">h</span><span class="o">@</span><span class="p">(</span><span class="kt">Node</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="n">r</span><span class="p">)</span><span class="w"> </span><span class="n">h'</span><span class="o">@</span><span class="p">(</span><span class="kt">Node</span><span class="w"> </span><span class="n">a'</span><span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="kr">_</span><span class="p">)</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">a'</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">merge</span><span class="w"> </span><span class="n">h'</span><span class="w"> </span><span class="n">h</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">rank</span><span class="w"> </span><span class="n">r'</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">rank</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Node</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">r'</span><span class="w"> </span><span class="n">l</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">otherwise</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Node</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="n">r'</span>
<span class="w"> </span><span class="kr">where</span><span class="w"> </span><span class="n">r'</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">merge</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="n">h'</span>
</pre></div>
<div class="mw-heading mw-heading4"><h4 id="Example">Example</h4></div><p>
An example of how the merge operation in a leftist tree works is depicted. The boxes represent each merge call.</p><ul class="gallery mw-gallery-packed">
<li class="gallerybox" style="width: 362px">
<div class="thumb" style="width: 360px;"><span typeof="mw:File"></span></div>
<div class="gallerytext"></div>
</li>
<li class="gallerybox" style="width: 362px">
<div class="thumb" style="width: 360px;"><span typeof="mw:File"></span></div>
<div class="gallerytext"></div>
</li>
<li class="gallerybox" style="width: 362px">
<div class="thumb" style="width: 360px;"><span typeof="mw:File"></span></div>
<div class="gallerytext"></div>
</li>
<li class="gallerybox" style="width: 362px">
<div class="thumb" style="width: 360px;"><span typeof="mw:File"></span></div>
<div class="gallerytext"></div>
</li>
<li class="gallerybox" style="width: 362px">
<div class="thumb" style="width: 360px;"><span typeof="mw:File"></span></div>
<div class="gallerytext"></div>
</li>
<li class="gallerybox" style="width: 362px">
<div class="thumb" style="width: 360px;"><span typeof="mw:File"></span></div>
<div class="gallerytext"></div>
</li>
<li class="gallerybox" style="width: 362px">
<div class="thumb" style="width: 360px;"><span typeof="mw:File"></span></div>
<div class="gallerytext"></div>
</li>
<li class="gallerybox" style="width: 362px">
<div class="thumb" style="width: 360px;"><span typeof="mw:File"></span></div>
<div class="gallerytext"></div>
</li>
<li class="gallerybox" style="width: 362px">
<div class="thumb" style="width: 360px;"><span typeof="mw:File"></span></div>
<div class="gallerytext"></div>
</li>
</ul><p>When the recursion unwinds, we swap left and right children if x.right.s_value &gt; x.left.s_value for every node x. In this case we swapped the subtrees rooted at nodes with keys 7 and 10.
</p><div class="mw-heading mw-heading3"><h3 id="Insertion_into_a_Min_HBLT">Insertion into a Min HBLT</h3></div>
<p>Insertion is done using the merge operation. An insertion of a node into an already existing Min HBLT, creates a HBLT tree of size one with that node and merges it with the existing tree.
</p>
<pre>INSERT (<i>A</i>, <i>x</i>)
<i>B</i>&nbsp;:= CREATE_TREE(<i>x</i>)
<b>return</b> MERGE(<i>A</i>, <i>B</i>)
</pre>
<div class="mw-heading mw-heading3"><h3 id="Deletion_of_Min_element_from_Min_HBLT">Deletion of Min element from Min HBLT</h3></div>
<p>The Min element in a Min HBLT is the root. Thus, in order to delete the Min, the root is deleted and its subtrees are merged to form the new Min HBLT.
</p>
<pre>DELETE_MIN(<i>A</i>)
<i>x</i>&nbsp;:= <i>A</i>.key
<i>A</i>&nbsp;:= MERGE (<i>A</i>.right, <i>A</i>.left)
<b>return</b> <i>x</i>
</pre>
<div class="mw-heading mw-heading3"><h3 id="Initializing_a_height_biased_leftist_tree">Initializing a height biased leftist tree</h3></div>

<p>Initializing a height biased leftist tree is primarily done in one of two ways. The first is to merge each node one at a time into one HBLT. This process is inefficient and takes O(<i>nlogn</i>) time. The other approach is to use a queue to store each node and resulting tree. The first two items in the queue are removed, merged, and placed back into the queue. This can initialize a HBLT in O(<i>n</i>) time. This approach is detailed in the three diagrams supplied. A min height biased leftist tree is shown.
</p><p>To initialize a min HBLT, place each element to be added to the tree into a queue. In the example (see Part 1 to the left), the set of numbers [4, 8, 10, 9, 1, 3, 5, 6, 11] are initialized. Each line of the diagram represents another cycle of the algorithm, depicting the contents of the queue. The first five steps are easy to follow. Notice that the freshly created HBLT is added to the end of the queue. In the fifth step, the first occurrence of an s-value greater than 1 occurs. The sixth step shows two trees merged with each other, with predictable results.
</p>
<div style="clear:both;" class=""></div>

<p>In part 2 a slightly more complex merge happens. The tree with the lower value (tree x) has a right child, so merge must be called again on the subtree rooted by tree x's right child and the other tree. After the merge with the subtree, the resulting tree is put back into tree x. The s-value of the right child (s=2) is now greater than the s-value of the left child (s=1), so they must be swapped. The s-value of the root node 4 is also now 2.
</p>
<div style="clear:both;" class=""></div>
<p>Part 3 is the most complex. Here, we recursively call merge twice (each time with the right child 's subtree that is not grayed out). This uses the same process described for part 2.
</p>
<div style="clear:both;" class=""></div>
<div class="mw-heading mw-heading3"><h3 id="Deletion_of_an_arbitrary_element_from_a_Min_HBLT">Deletion of an arbitrary element from a Min HBLT</h3></div>

<p>If we have a pointer to a node x in a Min HBLT, we can delete it as follows: Replace the node x with the result of merging its two subtrees and update the s-values of the nodes on the path from x to the root, swapping the right and left subtrees if necessary to maintain the leftist tree property.
</p><p>The upward traversal is continued until either we hit the root or the s-value does not change. Since we are deleting an element, the S-values on the path traversed cannot be increased. Every node that is already the right child of its parent and causes its parent's s-value to be decreased, will remain on the right. Every node that is its parent's left child and causes the parent's s-value to be decreased has to be swapped with its right sibling if the s-value becomes lower than the current s-value of the right child.
</p><p>Each node needs to have a pointer to its parent, so that we can traverse the path to the root updating the s-values.
</p><p>When the traversal ends at some node y, the nodes traversed all lie on the rightmost path rooted at node y. An example is shown below. It follows that the number of nodes traversed is at most log(m), m being the size of the subtree rooted at y. Thus, this operation also takes O(lg m) to perform.
</p>
<div class="mw-heading mw-heading2"><h2 id="Weight_biased_leftist_tree">Weight biased leftist tree</h2></div>
<p>Leftist trees can also be weight biased.<sup id="cite_ref-6" class="reference"><a href="#cite_note-6"><span class="cite-bracket">[</span>6<span class="cite-bracket">]</span></a></sup> In this case, instead of storing s-values in node x, we store an attribute w(<i>x</i>) denoting the number of nodes in the subtree rooted at <var style="padding-right: 1px;">x</var>:
</p><p>w(<i>x</i>) = w(<i>x</i>.right) + w(<i>x</i>.left) + 1
</p><p>WBLTs ensure w(x.left) ≥ w(x.right) for all internal nodes x. WBLT operations ensure this invariant by swapping the children of a node when the right subtree outgrows the left one, just as in HBLT operations.
</p>
<div class="mw-heading mw-heading3"><h3 id="Merging_two_Min_WBLTs">Merging two Min WBLTs</h3></div>
<p>The merge operation in WBLTs can be done using a single top to bottom traversal since the number of nodes in the subtrees are known prior to recursive call to merge. Thus, we can swap left and right subtrees if the total number of nodes in the right subtree and the tree to be merged is bigger than the number of nodes in the left subtree. This allows the operations be completed in a single path and so improves the time complexity of the operations by a constant factor.
</p><p>
The merge operation is depicted in the graph below.</p><ul class="gallery mw-gallery-packed">
<li class="gallerybox" style="width: 362px">
<div class="thumb" style="width: 360px;"><span typeof="mw:File"></span></div>
<div class="gallerytext"></div>
</li>
<li class="gallerybox" style="width: 362px">
<div class="thumb" style="width: 360px;"><span typeof="mw:File"></span></div>
<div class="gallerytext"></div>
</li>
<li class="gallerybox" style="width: 362px">
<div class="thumb" style="width: 360px;"><span typeof="mw:File"></span></div>
<div class="gallerytext"></div>
</li>
<li class="gallerybox" style="width: 362px">
<div class="thumb" style="width: 360px;"><span typeof="mw:File"></span></div>
<div class="gallerytext"></div>
</li>
<li class="gallerybox" style="width: 362px">
<div class="thumb" style="width: 360px;"><span typeof="mw:File"></span></div>
<div class="gallerytext"></div>
</li>
<li class="gallerybox" style="width: 362px">
<div class="thumb" style="width: 360px;"><span typeof="mw:File"></span></div>
<div class="gallerytext"></div>
</li>
<li class="gallerybox" style="width: 362px">
<div class="thumb" style="width: 360px;"><span typeof="mw:File"></span></div>
<div class="gallerytext"></div>
</li>
<li class="gallerybox" style="width: 362px">
<div class="thumb" style="width: 360px;"><span typeof="mw:File"></span></div>
<div class="gallerytext"></div>
</li>
<li class="gallerybox" style="width: 362px">
<div class="thumb" style="width: 360px;"><span typeof="mw:File"></span></div>
<div class="gallerytext"></div>
</li>
<li class="gallerybox" style="width: 362px">
<div class="thumb" style="width: 360px;"><span typeof="mw:File"></span></div>
<div class="gallerytext"></div>
</li>
</ul>
<div class="mw-heading mw-heading3"><h3 id="Other_operations_on_WBLT">Other operations on WBLT</h3></div>

<p>Insertions and deletion of the min element can be done in the same as for HBLTs using the merge operation.
</p><p>Although WBLTs outperform HBLTs in merge, insertion and deletion of the Min key by a constant factor, the <i>O</i>(log <i>n</i>) bound is not guaranteed when deleting an arbitrary element from WBLTs, since θ(<i>n</i>) nodes have to be traversed.
</p><p>If this was an HBLT, then deleting the leaf node with key 60 would take <i>O</i>(1) time and updating the s-values is not needed since the length of rightmost path for all the nodes does not change.
</p><p>But in an WBLT tree, we have to update the weight of each node back to the root, which takes <i>O</i>(<i>n</i>) worst case.
</p>
<div class="mw-heading mw-heading2"><h2 id="Variants">Variants</h2></div>
<p>Several variations on the basic leftist tree exist, which make only minor changes to the basic algorithm:
</p>
<ul><li>The choice of the left child as the taller one is arbitrary; a "rightist tree" would work just as well.</li>
<li>It is possible to avoid swapping children, but instead record <i>which</i> child is the tallest (in, for example, the least significant bit of the s-value) and use that in the merge operation.</li>
<li>The s-value used to decide which side to merge with could use a metric other than height. For example, weight (number of nodes) could be used.</li></ul>
<div class="mw-heading mw-heading2"><h2 id="References">References</h2></div>
<style data-mw-deduplicate="TemplateStyles:r1239543626">
/* start https://en.wikipedia.org/ */


.mw-parser-output .reflist{margin-bottom:0.5em;list-style-type:decimal}@media screen{.mw-parser-output .reflist{font-size:90%}}.mw-parser-output .reflist .references{font-size:100%;margin-bottom:0;list-style-type:inherit}.mw-parser-output .reflist-columns-2{column-width:30em}.mw-parser-output .reflist-columns-3{column-width:25em}.mw-parser-output .reflist-columns{margin-top:0.3em}.mw-parser-output .reflist-columns ol{margin-top:0}.mw-parser-output .reflist-columns li{page-break-inside:avoid;break-inside:avoid-column}.mw-parser-output .reflist-upper-alpha{list-style-type:upper-alpha}.mw-parser-output .reflist-upper-roman{list-style-type:upper-roman}.mw-parser-output .reflist-lower-alpha{list-style-type:lower-alpha}.mw-parser-output .reflist-lower-greek{list-style-type:lower-greek}.mw-parser-output .reflist-lower-roman{list-style-type:lower-roman}


/* end https://en.wikipedia.org/ */
</style><div class="reflist">
<div class="mw-references-wrap"><ol class="references">
<li id="cite_note-:0-1"><span class="mw-cite-backlink">^ <a href="#cite_ref-:0_1-0"><sup><i><b>a</b></i></sup></a> <a href="#cite_ref-:0_1-1"><sup><i><b>b</b></i></sup></a> <a href="#cite_ref-:0_1-2"><sup><i><b>c</b></i></sup></a></span> <span class="reference-text"><style data-mw-deduplicate="TemplateStyles:r1238218222">
/* start https://en.wikipedia.org/ */


.mw-parser-output cite.citation{font-style:inherit;word-wrap:break-word}.mw-parser-output .citation q{quotes:"\"""\"""'""'"}.mw-parser-output .citation:target{background-color:rgba(0,127,255,0.133)}.mw-parser-output .id-lock-free.id-lock-free a{background:url("./mw/Lock-green.svg")right 0.1em center/9px no-repeat}.mw-parser-output .id-lock-limited.id-lock-limited a,.mw-parser-output .id-lock-registration.id-lock-registration a{background:url("./mw/Lock-gray-alt-2.svg")right 0.1em center/9px no-repeat}.mw-parser-output .id-lock-subscription.id-lock-subscription a{background:url("./mw/Lock-red-alt-2.svg")right 0.1em center/9px no-repeat}.mw-parser-output .cs1-ws-icon a{background:url("./mw/Wikisource-logo.svg")right 0.1em center/12px no-repeat}body:not(.skin-timeless):not(.skin-minerva) .mw-parser-output .id-lock-free a,body:not(.skin-timeless):not(.skin-minerva) .mw-parser-output .id-lock-limited a,body:not(.skin-timeless):not(.skin-minerva) .mw-parser-output .id-lock-registration a,body:not(.skin-timeless):not(.skin-minerva) .mw-parser-output .id-lock-subscription a,body:not(.skin-timeless):not(.skin-minerva) .mw-parser-output .cs1-ws-icon a{background-size:contain;padding:0 1em 0 0}.mw-parser-output .cs1-code{color:inherit;background:inherit;border:none;padding:inherit}.mw-parser-output .cs1-hidden-error{display:none;color:var(--color-error,#d33)}.mw-parser-output .cs1-visible-error{color:var(--color-error,#d33)}.mw-parser-output .cs1-maint{display:none;color:#085;margin-left:0.3em}.mw-parser-output .cs1-kern-left{padding-left:0.2em}.mw-parser-output .cs1-kern-right{padding-right:0.2em}.mw-parser-output .citation .mw-selflink{font-weight:inherit}@media screen{.mw-parser-output .cs1-format{font-size:95%}html.skin-theme-clientpref-night .mw-parser-output .cs1-maint{color:#18911f}}@media screen and (prefers-color-scheme:dark){html.skin-theme-clientpref-os .mw-parser-output .cs1-maint{color:#18911f}}


/* end https://en.wikipedia.org/ */
</style><cite class="citation web cs1"><a rel="nofollow" class="external text" href="http://web.onda.com.br/abveiga/capitulo5-ingles.pdf">"Leftist Trees"</a> <span class="cs1-format">(PDF)</span>. <i>www.google.com</i><span class="reference-accessdate">. Retrieved <span class="nowrap">2019-05-31</span></span>.</cite></span>
</li>
<li id="cite_note-Crane1972-2"><span class="mw-cite-backlink">^ <a href="#cite_ref-Crane1972_2-0"><sup><i><b>a</b></i></sup></a> <a href="#cite_ref-Crane1972_2-1"><sup><i><b>b</b></i></sup></a></span> <span class="reference-text"><cite id="CITEREFCrane1972" class="citation cs2">Crane, Clark A. (1972), <i>Linear Lists and Priority Queues as Balanced Binary Trees</i> (Ph.D. thesis), Department of Computer Science, Stanford University, <a href="ISBN_(identifier)" class="mw-redirect" title="ISBN (identifier)">ISBN</a>&nbsp;<bdi>0-8240-4407-X</bdi>, <a rel="nofollow" class="external text" href="https://searchworks.stanford.edu/view/4591631">STAN-CS-72-259</a></cite></span>
</li>
<li id="cite_note-Cho96-3"><span class="mw-cite-backlink"><b><a href="#cite_ref-Cho96_3-0">^</a></b></span> <span class="reference-text"><cite id="CITEREFSeonghun_ChoSartaj_Sahni1996" class="citation cs2">Seonghun Cho; Sartaj Sahni (1996), <a rel="nofollow" class="external text" href="http://www.cise.ufl.edu/~sahni/papers/wblt.pdf">"Weight Biased Leftist Trees and Modified Skip Lists"</a> <span class="cs1-format">(PDF)</span>, <i>Journal of Experimental Algorithmics</i>, <b>3</b>: 2, <a href="CiteSeerX_(identifier)" class="mw-redirect" title="CiteSeerX (identifier)">CiteSeerX</a>&nbsp;<span class="id-lock-free" title="Freely accessible"><a rel="nofollow" class="external text" href="https://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.13.2962">10.1.1.13.2962</a></span>, <a href="Doi_(identifier)" class="mw-redirect" title="Doi (identifier)">doi</a>:<a rel="nofollow" class="external text" href="https://doi.org/10.1145%2F297096.297111">10.1145/297096.297111</a>, <a href="S2CID_(identifier)" class="mw-redirect" title="S2CID (identifier)">S2CID</a>&nbsp;<a rel="nofollow" class="external text" href="https://api.semanticscholar.org/CorpusID:17789668">17789668</a></cite></span>
</li>
<li id="cite_note-Sch24-4"><span class="mw-cite-backlink"><b><a href="#cite_ref-Sch24_4-0">^</a></b></span> <span class="reference-text"><cite id="CITEREFSchoenmakers2024" class="citation book cs1">Schoenmakers, Berry (2024). "Amortized Analysis of Leftist Heaps". <i>Principles of Verification: Cycling the Probabilistic Landscape</i>. Lecture Notes in Computer Science. Vol.&nbsp;15260. Springer. pp.&nbsp;<span class="nowrap">73–</span>84. <a href="ArXiv_(identifier)" class="mw-redirect" title="ArXiv (identifier)">arXiv</a>:<span class="id-lock-free" title="Freely accessible"><a rel="nofollow" class="external text" href="https://arxiv.org/abs/2411.11051">2411.11051</a></span>. <a href="Doi_(identifier)" class="mw-redirect" title="Doi (identifier)">doi</a>:<a rel="nofollow" class="external text" href="https://doi.org/10.1007%2F978-3-031-75783-9_3">10.1007/978-3-031-75783-9_3</a>. <a href="ISBN_(identifier)" class="mw-redirect" title="ISBN (identifier)">ISBN</a>&nbsp;<bdi>978-3-031-75782-2</bdi>.</cite></span>
</li>
<li id="cite_note-5"><span class="mw-cite-backlink"><b><a href="#cite_ref-5">^</a></b></span> <span class="reference-text"><cite id="CITEREFStewart1988" class="citation web cs1">Stewart, James (25 September 1988). <a rel="nofollow" class="external text" href="http://www.dgp.toronto.edu/people/JamesStewart/378notes/10leftist/">"LEFTIST TREES"</a>. <i>University of Toronto Dynamic Graphics Project</i><span class="reference-accessdate">. Retrieved <span class="nowrap">2019-05-31</span></span>.</cite></span>
</li>
<li id="cite_note-6"><span class="mw-cite-backlink"><b><a href="#cite_ref-6">^</a></b></span> <span class="reference-text"><cite id="CITEREFChoSahni1998" class="citation journal cs1">Cho, Seonghun; Sahni, Sartaj (September 1998). <a rel="nofollow" class="external text" href="http://doi.acm.org/10.1145/297096.297111">"Weight-biased Leftist Trees and Modified Skip Lists"</a>. <i>ACM Journal of Experimental Algorithmics</i>. <b>3</b>: 2. <a href="Doi_(identifier)" class="mw-redirect" title="Doi (identifier)">doi</a>:<a rel="nofollow" class="external text" href="https://doi.org/10.1145%2F297096.297111">10.1145/297096.297111</a>. <a href="ISSN_(identifier)" class="mw-redirect" title="ISSN (identifier)">ISSN</a>&nbsp;<a rel="nofollow" class="external text" href="https://search.worldcat.org/issn/1084-6654">1084-6654</a>. <a href="S2CID_(identifier)" class="mw-redirect" title="S2CID (identifier)">S2CID</a>&nbsp;<a rel="nofollow" class="external text" href="https://api.semanticscholar.org/CorpusID:17789668">17789668</a>.</cite></span>
</li>
</ol></div></div>
<div class="mw-heading mw-heading2"><h2 id="Further_reading">Further reading</h2></div>
<ul><li><cite id="CITEREFRobert_E._Tarjan1983" class="citation book cs1">Robert E. Tarjan (1983). <i>Data Structures and Network Algorithms</i>. SIAM. pp.&nbsp;<span class="nowrap">38–</span>42. <a href="ISBN_(identifier)" class="mw-redirect" title="ISBN (identifier)">ISBN</a>&nbsp;<bdi>978-0-89871-187-5</bdi>.</cite></li>
<li><cite id="CITEREFDinesh_P._MehtaSartaj_Sahni2004" class="citation book cs1">Dinesh P. Mehta; Sartaj Sahni (28 October 2004). <a rel="nofollow" class="external text" href="https://books.google.com/books?id=fQVZy1zcpJkC&amp;pg=SA5-PA1">"Chapter 5: Leftist trees"</a>. <i>Handbook of Data Structures and Applications</i>. CRC Press. <a href="ISBN_(identifier)" class="mw-redirect" title="ISBN (identifier)">ISBN</a>&nbsp;<bdi>978-1-4200-3517-9</bdi>.</cite></li></ul>
<div class="mw-heading mw-heading2"><h2 id="External_links">External links</h2></div>
<ul><li><a rel="nofollow" class="external text" href="http://www.cise.ufl.edu/~sahni/cop5536/powerpoint/lec11.ppt">Leftist Trees</a>, <a href="Sartaj_Sahni" title="Sartaj Sahni">Sartaj Sahni</a></li></ul></div><!--htdig_noindex--><div><div class="zim-footer">
This article is issued from <a class="external text" title="Last edited on 2025-06-06" href="https://en.wikipedia.org/wiki/?title=Leftist_tree&amp;oldid=1294289282">Wikipedia</a>. The text is available under <a class="external text" href="https://creativecommons.org/licenses/by-sa/4.0/deed.en">Creative Commons Attribution-Share Alike 4.0</a> unless otherwise noted. Additional terms may apply for the media files.
</div>
</div><!--/htdig_noindex--></div>
</div>
</main>
</div>
</div>
</div>

</body></html>